package org.myspringframework.aop.framework;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.myspringframework.beans.BeansException;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

/**
 *   基于反射的执行通知方法的 【调用链】
 * 可被反射的方法执行器(和MethodInterceptor对应),负责执行拦截器链(proceed)
 * 用于封装方法调用信息的类，它实现了 MethodInvocation 接口。
 * 在 AOP 拦截链中，每个通知都会被传递一个 MethodInvocation 对象，它包含了目标方法的信息以及相关的上下文信息，以便在通知中进行处理。
 * 在 AOP 拦截链中，MethodInvocation 对象被依次传递给每个 MethodInterceptor 的 invoke 方法。
 * 每个拦截器可以在 invoke 方法中对目标方法进行前置处理、后置处理等操作。
 * 同时，拦截器可以选择是否调用 MethodInvocation 的 proceed() 方法，该方法用于继续执行拦截链中的下一个拦截器或者执行目标方法。
 * 是代理执行的入口。然后内部会把所有的 增强器 都拿出来 递归执行
 */
public class ReflectiveMethodInvocation implements MethodInvocation {

    // 代理目标对象
    protected final Object target;
    // 被拦截的原目标方法
    protected final Method method;
    // 方法入参
    protected final Object[] arguments;
    //存放拦截器链methodInterceptorList（即所有的环绕通知(转换后)）
    protected  List<Object> interceptorsAndDynamicInterceptionAdvice;
    //记录拦截器链的下标
    private int currentInterceptorIndex = -1;

    public ReflectiveMethodInvocation(Object target, Method method, Object[] arguments,List<Object> interceptorsAndDynamicInterceptionAdvice) {
        this.target = target;
        this.method = method;
        this.arguments = arguments;
        this.interceptorsAndDynamicInterceptionAdvice=interceptorsAndDynamicInterceptionAdvice;
    }

    //返回正在被调用得方法
    @Override
    public Method getMethod() {
        return method;
    }

    @Override
    public Object[] getArguments() {
        return arguments;
    }

    //运用 递归调用 的方式 调用所有methodInterceptor环绕通知  https://blog.csdn.net/weixin_39977988/article/details/127803553
    //在methodInterceptor的通知中，会继续调用这个methodInvocation的proceed()方法
    @Override
    public Object proceed() throws Throwable {
        if (this.currentInterceptorIndex == this.interceptorsAndDynamicInterceptionAdvice.size() - 1) {
            //已经走完了拦截器链，执行原方法
            return invokeJoinpoint();
        } else {
            Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicInterceptionAdvice.get(++this.currentInterceptorIndex);
            if (interceptorOrInterceptionAdvice instanceof MethodInterceptor) {
                MethodInterceptor methodInterceptor = (MethodInterceptor) interceptorOrInterceptionAdvice;
                return methodInterceptor.invoke(this);
            }else{
                throw new BeansException("拦截器链执行失败:"+interceptorOrInterceptionAdvice);
            }
        }
    }

    // 返回保存当前连接点静态部分的【对象】。  这里一般指的target
    @Override
    public Object getThis() {
        return target;
    }

    // 返回此静态连接点  一般就为当前的Method
    @Override
    public AccessibleObject getStaticPart() {
        return method;
    }

    protected Object invokeJoinpoint() throws Throwable {
        return  method.invoke(target,arguments);
    }

}